

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>

#include "mqtt_config.h"
#include "mqtt_log.h"
#include "mqttclient.h"

#include "event2/event.h"
// #include "event-internal.h"


#include <iostream>
#include <thread>
#include <mutex>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include "linux/can.h"
#include "linux/can/raw.h"

// #include "lib.h"
#include "logging.h"

#include "socket_can_client_raw.h"
#include "can_client.h"

#include "common_util.h"
#include "safeuqeue.h"
#include "tbox_msg_prase.h"
#include "http_register.h"

#include "json_msg_chassis.h"
#include "json_prase_recv.h"
#include "json_rw_ID.h"

std::shared_ptr<spdlog::logger> fileLogger = NULL;
std::shared_ptr<canbus::SocketCanClientRaw> can_client = NULL;
std::shared_ptr<SafeQueue::SafeQueue<canbus::CanFrame>> sCanRecvQueue = NULL;
std::shared_ptr<SafeQueue::SafeQueue<canbus::CanFrame>> sCanSendQueue = NULL;

httpRegisterDev::httpRegister http_regist;
std::string reportJsonToString;
tbox_msg::parse_vin parseVIN;
tbox_msg::jsonMsgRepChassis json_msg_rep;
tbox_msg::jsonPraseRecv json_prase_recv;
tbox_msg::jsonTboxId json_tbox_id;

std::string vcu_user_name;
std::string vcu_password;
std::string vcu_client_id;
std::string tbox_config_path;
std::string public_1002;
std::string sub_1002;
std::string sub_1001_1004;
std::string sub_1003;

bool is_register_ok = false;
bool is_get_vin = false;
bool is_rep_data_update = false;

#define CMD_CAN0_SET_BAUD_RATE "sudo ip link set can0 type can bitrate 500000 sample-point 0.750 sjw 1 restart-ms 100"
#define CMD_CAN0_OPEN "ifconfig can0 up"
#define CMD_CAN0_CLOSE "ifconfig can0 down"

const int32_t CAN_FRAME_SIZE = 8;
const int32_t MAX_CAN_SEND_FRAME_LEN = 1;
const int32_t MAX_CAN_RECV_FRAME_LEN = 2; // 每次收两条处理
const int32_t CANBUS_MESSAGE_LENGTH = 8;  // according to ISO-11891-1

static void topic1_handler(void *client, message_data_t *msg)
{
    (void)client;
    // spdlog::warn("----------------topic1_handler -----------{}", msg->message->payloadlen);
    LOG_INFO("{}", (char *)msg->message->payload);
    json_prase_recv.parse_json((char *)msg->message->payload);
}

void *mqtt_publish_thread(void *arg)
{
    mqtt_client_t *client = (mqtt_client_t *)arg;
    int is_mqtt_connect = -1;

    char buf[8192] = {0};
    char client_id[64] = {0};
    char user_name[64] = {0};
    char password[64] = {0};
    mqtt_message_t msg;

    memset(&msg, 0, sizeof(msg));
    sprintf(buf, "welcome to mqttclient, this is a publish test...");

    sleep(2);
    // 设置日志级别为 DEBUG
    spdlog::set_level(spdlog::level::debug);

    while (1)
    {

        if ((is_get_vin) && (!is_register_ok))
        {
            http_regist.setRegisterInfo(parseVIN.VIN);

            int ret = http_regist.register_device(vcu_user_name, vcu_password, vcu_client_id);
            if (ret == 0)
            {
                is_register_ok = true;
                LOG_INFO("vcu_user_name: {} ,vcu_password: {} ,vcu_client_id: {} ",
                         vcu_user_name.c_str(), vcu_password.c_str(), vcu_client_id.c_str());
            }
            // 添加 topic  拼接
            // /IOV/thing/T-BOX/event/property/response // fanhui 1002
            // /IOV/thing/T-BOX/service/request  //
            // /IOV/thing/T-BOX/event/response

            //          TBOX设备属性上传响应topic
            //          服务调用topic  dianhuo
            //          事件响应topic
            public_1002 = "/" + json_tbox_id.product_key + "/" + json_tbox_id.device_name + "/IOV/thing/T-BOX/event/property/request"; // 发布1002
            // sub_1002 = "/" + json_tbox_id.product_key + "/" + json_tbox_id.device_name + "/IOV/thing/T-BOX/event/property/response"; // 接收1002
            sub_1001_1004 = "/" + json_tbox_id.product_key + "/" + json_tbox_id.device_name + "/IOV/thing/T-BOX/service/request"; // 接收 1004 1001
            // sub_1003 = "/" + json_tbox_id.product_key + "/" + json_tbox_id.device_name + "/IOV/thing/T-BOX/event/property/response"; // 接收 1003 ，故障上报
            LOG_INFO("public_1002 :{} ,sub_1001_1004 :{} , {}", public_1002, sub_1001_1004);
        }

        if (is_register_ok)
        {

            if (is_mqtt_connect) // 未连接
            {
                strcpy(client_id, vcu_client_id.c_str());
                strcpy(user_name, vcu_user_name.c_str());
                strcpy(password, vcu_password.c_str());
                mqtt_set_client_id(client, client_id);
                mqtt_set_user_name(client, user_name);
                mqtt_set_password(client, password);
                mqtt_set_clean_session(client, 1);
                is_mqtt_connect = mqtt_connect(client); // return 0 is ok
                mqtt_subscribe(client, sub_1001_1004.c_str(), QOS0, topic1_handler);
            }
            else
            {
                std::string str_json;
                json_msg_rep.jsonDocTostring(str_json);
                strcpy(buf, str_json.c_str());
                msg.payload = (void *)buf;
                msg.qos = QOS0;
                // if (is_rep_data_update)
                // {
                    mqtt_publish(client, public_1002.c_str(), &msg);
                    // is_rep_data_update = false;
                // }
            }
        }
        sleep(10);
    }
}

void prase_vcu_report(canbus::CanFrame frame)
{
    uint32_t can_id;
    can_id = frame.id;
    switch (can_id)
    {
    case 0x18FF4024: // VIN //"LMY1C22C00001";
        parseVIN.parse(frame.data, 8);
        json_msg_rep.VIN = parseVIN.VIN;
        console_show_can_msg(frame);
        is_get_vin = true;
        is_rep_data_update = true;
        break;
    case 0x18FF4124: // RCU
        json_msg_rep.RCU = hexToStr(frame.data, 8);
        break;
    case 0x18FF4224: // BCM
        json_msg_rep.BCM = hexToStr(frame.data, 8);
        break;
    case 0x18FF4324: // DC
        json_msg_rep.DC = hexToStr(frame.data, 8);
        break;
    case 0x18FF4424: // EHB1
        json_msg_rep.EHB1 = hexToStr(frame.data, 8);
        break;
    case 0x18FF4524: // EHB2
        json_msg_rep.EHB2 = hexToStr(frame.data, 8);
        break;
    case 0x18FF4624: // EPB1
        json_msg_rep.EPB1 = hexToStr(frame.data, 8);
        break;
    case 0x18FF4724: // EPB2
        json_msg_rep.EPB2 = hexToStr(frame.data, 8);
        break;
    case 0x18FF4824: // EPS1
        json_msg_rep.EPS1 = hexToStr(frame.data, 8);
        break;
    case 0x18FF4924: // EPS2
        json_msg_rep.EPS2 = hexToStr(frame.data, 8);
        break;
    case 0x18FF4A24: // BMS1
        json_msg_rep.BMS1 = hexToStr(frame.data, 8);
        break;
    case 0x18FF4B24: // BMS2
        json_msg_rep.BMS2 = hexToStr(frame.data, 8);
        break;
    case 0x18FF4C24: // BMS3
        json_msg_rep.BMS3 = hexToStr(frame.data, 8);
        break;
    case 0x18FF4D24: // BMS4
        json_msg_rep.BMS4 = hexToStr(frame.data, 8);
        break;
    case 0x18FF4E24: // MCU1
        json_msg_rep.MCU1 = hexToStr(frame.data, 8);
        break;
    case 0x18FF4F24: // MCU2
        json_msg_rep.MCU2 = hexToStr(frame.data, 8);
        break;
    case 0x18FF1824: // VEH1
        json_msg_rep.VEH1 = hexToStr(frame.data, 8);
        // 作为数据判断帧
        break;
    case 0x18FF1924: // VEH2
        json_msg_rep.VEH2 = hexToStr(frame.data, 8);
        break;
    case 0x18FF1A24: // VEH3
        json_msg_rep.VEH3 = hexToStr(frame.data, 8);
        break;
    case 0x18FF1B24: // event
        json_msg_rep.event = hexToStr(frame.data, 8);
        break;
    case 0x18FF0723: // TBOX_OK
        json_msg_rep.TBOX_OK = hexToStr(frame.data, 8);
        break;
    case 0x100: // TBOX_sleep
        json_msg_rep.TBOX_sleep = hexToStr(frame.data, 8);
        break;

    default:
        break;
    }
    json_msg_rep.changeReportJson();
}

void parse_can_recv_msg()
{
    canbus::CanFrame can_frame_;
    static int recv_cnt = 0;
    while (1)
    {
        // spdlog::info("======{} =====",sCanRecvQueue->mqueueSize());
        if (!sCanRecvQueue->empty())
        {
            sCanRecvQueue->tryPop(can_frame_);
            // char can_id_buf[4];
            // can_id_buf[3] = static_cast<char>(can_frame_.id);
            // can_id_buf[2] = static_cast<char>(can_frame_.id >> 8);
            // can_id_buf[1] = static_cast<char>(can_frame_.id >> 16);
            // can_id_buf[0] = static_cast<char>(can_frame_.id >> 24);
            // std::string canID = hexToStr(can_id_buf, 4);
            // std::string canData = hexToStr(can_frame_.data, 8);
            // std::string canRram = canID + " " + canData;
            // spdlog::info("can_cnt :{}, can_recv :{} can_data : {}", recv_cnt++, canRram.c_str() ,canData.c_str());

            prase_vcu_report(can_frame_);
            // if (is_get_vin)
            // {
            //     std::string chassis_vin = parseVIN.VIN;
            //     // spdlog::info("parseVIN.VIN:{};", chassis_vin.c_str());
            // }
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
}

#if 0

void timerCallback(evutil_socket_t fd, short events, void* arg) {
    std::cout << "Timer expired" << std::endl;

    // 停止事件循环
    event_base* base = static_cast<event_base*>(arg);
    event_base_loopbreak(base);
}

int main_1() {
    // 创建事件基础
    event_base* base = event_base_new();
    if (!base) {
        std::cerr << "Failed to create event base" << std::endl;
        return 1;
    }
    std::cout << "start event..." << std::endl;

    // 创建定时器事件
    timeval tv = {2, 0};  // 2 秒
    event* timerEvent = evtimer_new(base, timerCallback, base);
    if (!timerEvent) {
        std::cerr << "Failed to create timer event" << std::endl;
        return 1;
    }

    // 添加定时器事件
    if (evtimer_add(timerEvent, &tv) < 0) {
        std::cerr << "Failed to add timer event" << std::endl;
        return 1;
    }

    // 启动事件循环
    event_base_dispatch(base);

    // 清理资源
    event_free(timerEvent);
    event_base_free(base);

    return 0;
}

#endif

int main(void)
{
    int res;
    bool ret = false;
    char *current_dir;
    std::string retRequest;
    // event_base* base = event_base_new();
    // pthread_t thread1;
    // pthread_t canrecv_thread;

    mqtt_client_t *client = NULL;
    sCanRecvQueue = std::make_shared<SafeQueue::SafeQueue<canbus::CanFrame>>();
    sCanSendQueue = std::make_shared<SafeQueue::SafeQueue<canbus::CanFrame>>();

    InitLogger();

    json_msg_rep.initReportJson();

    current_dir = get_current_dir_name();
    tbox_config_path = json_tbox_id.get_filecontent(file_topdir, "my_test.json");
    ret = json_tbox_id.tbox_read_id(tbox_config_path);
    if (ret == true)
    {
        vcu_client_id = json_tbox_id.client_id;
        vcu_user_name = json_tbox_id.user_name;
        vcu_password = json_tbox_id.password;
        LOG_INFO("vcu_client_id :{} ,vcu_user_name :{} ,vcu_password: {} ", vcu_client_id, vcu_user_name, vcu_password);
        public_1002 = "/" + json_tbox_id.product_key + "/" + json_tbox_id.device_name + "/IOV/thing/T-BOX/event/property/request"; // 发布1002
        // sub_1002 = "/" + json_tbox_id.product_key + "/" + json_tbox_id.device_name + "/IOV/thing/T-BOX/event/property/response"; // 接收1002
        sub_1001_1004 = "/" + json_tbox_id.product_key + "/" + json_tbox_id.device_name + "/IOV/thing/T-BOX/service/request"; // 接收 1004 1001
        // sub_1003 = "/" + json_tbox_id.product_key + "/" + json_tbox_id.device_name + "/IOV/thing/T-BOX/event/property/response"; // 接收 1003 ，故障上报
        LOG_INFO("public_1002 :{} ,sub_1001_1004 :{} ", public_1002, sub_1001_1004);
        is_register_ok = true;
        is_get_vin = true;
    }
    free(current_dir);

    // canbus::SocketCanClientRaw can_client;
    can_client = std::make_shared<canbus::SocketCanClientRaw>();
    can_client->Init("can0");
    can_client->Start();

    printf("\nwelcome to mqttclient test...\n");

    // register_device();

    mqtt_log_init();

    // fileLogger = spdlog::rotating_logger_mt("fileLogger", "./basic.log", 1024 * 1024 * 100, 10);

    client = mqtt_lease();

    // #ifdef TEST_USEING_TLS
    //     mqtt_set_port(client, "8883");
    //     mqtt_set_ca(client, (char *)test_ca_get());
    // #else
    //     mqtt_set_port(client, "1883");
    // #endif

    mqtt_set_port(client, "18831");
    mqtt_set_host(client, "iot-mqtt-test.imuyuan.com");

    ////mqtt_set_port(client, "1883");
    ////mqtt_set_host(client, "192.168.2.42");
    ////mqtt_set_host(client, "10.21.40.169");
    // mqtt_set_client_id(client, "4pTIqmfI7NvILH48etpUhd|securemode=3,signmethod=hmacsha1|");
    // mqtt_set_user_name(client, "4pTIqmfI7NvILH48etpUhd&Az6yWDsy4hPc");
    // mqtt_set_password(client, "DFF70579FA426950112A820360CE74D54D3B829F");
    // mqtt_set_clean_session(client, 1);
    // mqtt_connect(client);
    // mqtt_subscribe(client, "topic1_subscribe", QOS0, topic1_handler);

    std::thread can_recv_t(&canbus::SocketCanClientRaw::RecvThreadFunc, can_client);
    std::thread can_send_t(&canbus::SocketCanClientRaw::SendThreadFunc, can_client);
    std::thread parse_can_recv_msg_t(parse_can_recv_msg);
    std::thread mqtt_pub_t(mqtt_publish_thread, client);

    if (mqtt_pub_t.joinable())
    {
        mqtt_pub_t.join();
    }
    if (can_recv_t.joinable())
    {
        std::cout << "can_recv.join(); " << std::endl;
        can_recv_t.join();
    }
    if (can_send_t.joinable())
    {
        std::cout << "can_send_t.join(); " << std::endl;
        can_send_t.join();
    }

    if (parse_can_recv_msg_t.joinable())
    {
        std::cout << "parse_can_recv_msg_t.join(); " << std::endl;
        parse_can_recv_msg_t.join();
    }

    while (1)
    {
        sleep(100);
    }
}
